JvnWrapperCreator.java

Go to the documentation of this file.
00001 
00009 package jvn;
00010 
00011 
00012 //import java.io.*;
00013 import java.io.File;
00014 import java.io.FileWriter;
00015 //import java.io.StringWriter;
00016 import java.lang.reflect.Constructor;
00017 import java.lang.reflect.Method;
00018 import java.lang.reflect.Modifier;
00019 import java.util.Vector;
00020 import java.util.logging.Logger;
00021 import java.util.regex.Matcher;
00022 import java.util.regex.Pattern;
00023 
00024 import org.apache.velocity.Template;
00025 import org.apache.velocity.VelocityContext;
00026 import org.apache.velocity.app.VelocityEngine;
00027 
00036 public class JvnWrapperCreator extends ClassLoader {
00037 
00038         //private static File currentFile = null;
00039         //private static String currentFilename = null;
00040 
00041         // TODO: CHECK pattern for package.
00045         private static Pattern pattern = Pattern.compile("^([A-Za-z][A-Za-z0-9.]*)+$");
00046         private static Matcher matcher;
00047         
00057         public static void main(String[] args) {
00058                 execute(args);
00059         }
00060 
00065         private static void execute(String [] args) {
00066                 String className;
00067                 Vector<Method> writeMethods;
00068                 Vector<Method> readMethods;             
00069                 Vector<Method> normalMethods;
00070                 JvnWrapperCreator creator;
00071                 
00072                 
00073                 creator = new JvnWrapperCreator();
00074                 writeMethods = new Vector<Method>();
00075                 readMethods = new Vector<Method>();
00076                 normalMethods = new Vector<Method>();
00077 
00078                 System.out.println("Usage: JvnWrapperCreator <complete class names (without \".class\")>");
00079                 //System.out.println("For now, classes are not supposed to have a constructor of the following form:");
00080                 //System.out.println("public Foo(java.lang.Serializable o);");
00081                 //System.out.println("Read the source for more details.");
00082 
00083                 if (args.length != 0) {
00084                         String name;
00085                         for (String s : args) {
00086                                 // Stupid bug, simple fix: don't forget to clear our
00087                                 // internal structures for each file !
00088                                 writeMethods.clear();
00089                                 readMethods.clear();
00090                                 normalMethods.clear();
00091                                 
00092                                 matcher = pattern.matcher(s);
00093                                 if (matcher.matches()) {
00094                                         // Classes are supposed to be under the "build" folder.
00095                                         //currentFilename = s.replace('.', '/') + ".class";
00096                                         //currentFile = new File("build/" + currentFilename);
00097                                         name = s;
00098                                         //System.out.println(name);
00099                                         Logger.global.info("Treating class \"" + name +"\"");
00100                                         try {
00101                                                 JvnWrite w;
00102                                                 JvnRead r;
00103 
00104                                                 //System.out.println(name);
00105 
00106                                                 Class c = creator.loadClass(name,true);
00107 
00108                                                 if (c != null) {
00109 
00110                                                         Method [] methods = c.getDeclaredMethods();
00111                                                         Constructor [] constructors = c.getConstructors();
00112 
00113                                                         //System.out.println("Methods in \"" + name + "\":");
00114                                                         for (Method m : methods) {
00115                                                                 //System.out.print(m.toGenericString());
00116                                                                 
00117                                                                 // Don't generate wrappers for PROTECTED or PRIVATE methods !
00118                                                                 if ((m.getModifiers() & (Modifier.PROTECTED | Modifier.PRIVATE)) != 0) {
00119                                                                         continue;
00120                                                                 }
00121 
00122                                                                 w = m.getAnnotation(JvnWrite.class);
00123                                                                 r = m.getAnnotation(JvnRead.class);
00124 
00125                                                                 // Do something if
00126                                                                 // annotation @JvnWrite is present
00127                                                                 // XOR
00128                                                                 // annotation @JvnRead is present
00129                                                                 // (AND makes no sense).
00130                                                                 if ((w != null) ^ (r != null)) {
00131                                                                         if (w != null) {
00132                                                                                 // Add method to list of @JvnWrite methods.
00133                                                                                 Logger.global.info("@JvnWrite on method \"" + m.toGenericString() + "\".");
00134                                                                                 
00135                                                                                 writeMethods.add(m);
00136                                                                         }
00137                                                                         else {
00138                                                                                 // Add method to list of @JvnRead methods.
00139                                                                                 Logger.global.info("@JvnRead on method \"" + m.toGenericString() + "\".");
00140 
00141                                                                                 readMethods.add(m);
00142                                                                         }
00143                                                                 }
00144                                                                 else if ((w != null) && (r != null)) {
00145                                                                         System.err.println("Having both @JvnWrite and @JvnRead on a method does not make any sense !");
00146                                                                 }
00147                                                                 else {
00148                                                                         normalMethods.add(m);
00149                                                                 }
00150 
00151                                                                 System.out.println("");
00152 
00153                                                         }
00154                                                         
00155                                                         className = name;
00156                                                         
00157                                                         generateOneFile(className, readMethods, writeMethods, normalMethods, constructors);
00158                                                 }
00159                                                 else {
00160                                                         System.err.println("Error: couldn't load class \"");
00161                                                 }
00162 
00163                                         } catch (ClassNotFoundException e) {
00164                                                 System.err.println("Error: class \"" + s + "\" not found !");
00165                                                 e.printStackTrace();
00166                                         }
00167 
00168                                 }
00169                                 else {
00170                                         System.err.println("Error: invalid filename \"" + s + "\" !");
00171                                 }
00172                         }
00173 
00174                 }
00175                 else {
00176 
00177                 }
00178 
00179         }
00180         
00188         private static void generateOneFile(String wholeClassName, Vector<Method> readMethods, Vector<Method> writeMethods, Vector<Method> normalMethods, Constructor[] constructors) {
00189                 String packageName;
00190                 String className;
00191                 String [] strings;
00192                 
00193                 Vector<Signature> signatures = new Vector<Signature>();
00194                 
00195                 for (Constructor c : constructors) {
00196                         Signature s = new Signature();
00197                         s.setValues(c);
00198                         signatures.add(s);
00199                 }
00200 
00201                 for (Method m : readMethods) {
00202                         Signature s = new Signature();
00203                         s.setValues(m);
00204                         signatures.add(s);
00205                 }
00206 
00207                 for (Method m : writeMethods) {
00208                         Signature s = new Signature();
00209                         s.setValues(m);
00210                         signatures.add(s);
00211                 }
00212                 
00213                 for (Method m : normalMethods) {
00214                         Signature s = new Signature();
00215                         s.setValues(m);
00216                         signatures.add(s);
00217                 }
00218 
00219                 
00220                 strings = wholeClassName.split("\\.");
00221 
00222                 // Class name is the last part of the whole class name.
00223                 if (strings.length > 1) {
00224                         packageName = new String(strings[0]);
00225                 }
00226                 else {
00227                         packageName = null;
00228                         if (strings.length != 1) {
00229                                 // Not supposed to occur !
00230                                 System.err.println("Incorrect class name !");
00231                                 return; // THIS returns !
00232                         }
00233                 }
00234                 className = strings[strings.length - 1];
00235 
00236                 // Package name is the rest of the whole class name.
00237                 // (Hey, no string "join" operation in Java ?)
00238                 if (packageName != null) {
00239                         // If there's a package name (i.e. if strings.length > 1)
00240                         for (int i = 1; i < strings.length - 1; i++) {
00241                                 packageName = packageName + "." + strings[i];
00242                         }
00243                 }
00244                 
00245                 
00246                 
00247                 // get & initialize the velocity engine
00248                 VelocityEngine ve = new VelocityEngine();
00249                 
00250                 try {
00251                         ve.init();
00252                         
00253                         // get the template
00254                         Template t = ve.getTemplate("jvnwrappercreator.vm");
00255                         // create a context & add data
00256                         VelocityContext context = new VelocityContext();
00257                         context.put("className", className);
00258                         context.put("packageName", packageName);
00259                         context.put("constructorsAndMethods",signatures);
00260                         
00261                         /*for (Constructor c : constructors) {
00262                                 System.out.println(c.toGenericString());
00263                                 modifiers.add(Modifier.toString(c.getModifiers()));
00264                         }*/
00265                         
00266                         //System.out.println(className);
00267                         //System.out.println(packageName);
00268                         
00269                         // perform generation
00270                         //StringWriter writer = new StringWriter();
00271                         if (packageName == null) {
00272                                 packageName = "";
00273                         }
00274                         File file = new File("src/" + packageName.replace('.', '/') + "/Jvn" + className + ".java");
00275                         FileWriter writer = new FileWriter(file);
00276                         t.merge(context, writer);
00277                         writer.flush();
00278                         //System.out.println(writer.toString());
00279                 }
00280                 catch (Exception e) {
00281                         e.printStackTrace(System.err);
00282                 }
00283         }
00284 
00285         protected synchronized Class<?> loadClass(final String name,final boolean resolve) throws ClassNotFoundException {
00286                 //FileInputStream fis;
00287 
00288         return super.loadClass(name, resolve);
00289         }
00290             
00291     // This attempt at loading a class, found in the Adapt example of ASM and
00292     // the Java Developer Almanach, doesn't work properly. With it, annotations
00293     // are more or less stripped - that is, they don't appear in
00294     // getAnnotations()
00295     // on methods, even though the irc.JvnWrite and irc.JvnRead classes are loaded,
00296     // but not kept by the JVM (loaded as many times as needed).
00297     // So we're giving up, after several hours of work.
00298         /*protected synchronized Class<?> loadClass(final String name,final boolean resolve) throws ClassNotFoundException {
00299                 //FileInputStream fis;
00300 
00301         // /!\ Do not load system classes ourselves:
00302                 //     it's forbidden and throws a security exception !
00303                 if (name.startsWith("java.")) {
00304                 System.out.println("Delegating loading of class \"" + name + "\" to parent.");
00305             return super.loadClass(name, resolve);
00306         }
00307                 else {
00308 
00309 
00310             //fis = getResourceAsStream(currentFilename);
00311                 try {
00312                         fis = new FileInputStream(currentFile);
00313                 } catch (FileNotFoundException e1) {
00314                         System.err.println("Error: file \"" + currentFile.getName() + "\" not found !");
00315                         return null; // THIS returns !
00316                 }
00317 
00318                 long length = currentFile.length();
00319 
00320                 if (length > Integer.MAX_VALUE) {
00321                         System.err.println("Error: file \"" + currentFile.getName() + "\" too large !");
00322                         return null; // THIS returns !
00323                 }
00324 
00325                 byte [] bytes = new byte[(int)length];
00326 
00327                 int offset = 0;
00328                 int numRead = 0;
00329 
00330                 try {
00331                         while (offset < bytes.length && (numRead = fis.read(bytes,offset,bytes.length-offset)) >= 0) {
00332                                 offset += numRead;
00333                         }
00334                 } catch (IOException e) {
00335                         System.err.println("Error: couldn't read file\"" + currentFile.getName() + "\"");
00336                         return null; // THIS returns !
00337                 }
00338 
00339                 if (offset < bytes.length) {
00340                         System.err.println("Error: couldn't read file\"" + currentFile.getName() + "\"");
00341                         return null; // THIS returns !
00342                 }
00343 
00344                 try {
00345                         fis.close();
00346                 } catch (IOException e) {
00347                         System.err.println("Error: couldn't close file\"" + currentFile.getName() + "\"");
00348                         // Supposed to be fatal ?
00349                 }
00350 
00351                 // returns the adapted class
00352                 Class<?> c = defineClass(name, bytes, 0, bytes.length);
00353                 return c;
00354         }
00355         }*/
00356 
00357         /*protected synchronized Class<?> findClass(final String name) throws ClassNotFoundException {
00358         System.out.println("findClass(\"" + name + "\")");
00359         return null;
00360         }*/
00361         
00362 }

Generated on Wed Jan 2 10:15:54 2008 for Javanaise by  doxygen 1.5.4